﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using iMapa.Helper;
using Emgu.CV;
using Emgu.CV.UI;
using Emgu.CV.Structure;
using System.IO;

namespace Testing
{
    public partial class Perform : Form
    {
        private PointRegister pr;
        private Capture capture;
        private int length;
        private int position = 0;
        private int lastpos=-1;
        private int samecount = 0;
        private string filename;
        SpotDetector sd = new SpotDetector();
        System.Text.StringBuilder output;

        int currentfile = 0;

        int diffThs = 30;
        int intensityThs = 60;
        double blobThs = 7;

        public Perform()
        {
            InitializeComponent();
            pictureBox1.FunctionalMode = ImageBox.FunctionalModeOption.Minimum;
            using (StreamWriter outfile = new StreamWriter(Program.outputFilename, false))
            {
                outfile.Write("");
            }
            Application.Idle += ProcessFrame;
        }

        public void ProcessFrame(object sender, EventArgs e)
        {
            if (capture == null)
            {
                currentfile = 0;
                OpenVideo(Program.dir + Program.files[0]);
                //this.diffThs = 10;
                //intensityThs = 50;
                //blobThs = 1;
            }
            position = (int)capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
            if (lastpos==position)
            { samecount++; }
            if(samecount>2){
                using (StreamWriter outfile = new StreamWriter(Program.outputFilename,true))
                {
                    outfile.Write(output);
                }
                ContinueNext();
            }
            Image<Bgr, Byte> frame = capture.QueryFrame();

            Point? p = sd.getSpot(frame, diffThs, intensityThs, blobThs);
            Point? m = pr.getPointForFrame(position);
            if (p.HasValue)
            {
                DrawDot(frame, p.Value, false);
                if (m.HasValue)
                {
                    //DrawDot(frame, m.Value, true);
                    output.AppendFormat("{0};{1};{2};{3};{4};{5};{6}\n", filename, position, diffThs, intensityThs, blobThs, "OK", (int)CountDistance(p.Value, m.Value));
                }
                else
                {
                    output.AppendFormat("{0};{1};{2};{3};{4};{5};{6}\n", filename, position, diffThs, intensityThs, blobThs, "MisDetected", "");
                }

            }
            else
            {
                if (m.HasValue)
                {
                    //DrawDot(frame, m.Value, true);
                    output.AppendFormat("{0};{1};{2};{3};{4};{5};{6}\n", filename, position, diffThs, intensityThs, blobThs, "UnDetected", "");
                }
                else
                {
                    output.AppendFormat("{0};{1};{2};{3};{4};{5};{6}\n", filename, position, diffThs, intensityThs, blobThs, "OK", "");
                }
            }
            Image<Gray, float> diff=null;
            try
            {
                diff = AbsDiffFrame.getInstance().computeAbsDiffFrame(frame.Convert<Gray, Byte>());
                double[] minval, maxval;
                Point[] minP, maxP;
                diff.MinMax(out minval, out maxval, out minP, out maxP);
                if (diff.Data[maxP[0].Y, maxP[0].X, 0] > 20)
                    DrawDot(diff, maxP[0]);
            }
            catch { }
            imageBox1.Image = diff;
            pictureBox1.Image = frame;
            label1.Text = "" + position + "/" + length;
            lastpos = position;
        }

        private void ContinueNext()
        {
            if (currentfile == Program.files.Length - 1)
            {
                if (!NextValue())
                {
                    Application.Idle -= ProcessFrame;
                }
                
            }
            else
            {
                currentfile += 1;
                OpenVideo(Program.dir + Program.files[currentfile]);
            }
        }

        private bool NextValue()
        {
            return false;
            currentfile = 0;
            OpenVideo(Program.dir + Program.files[0]);
            int max = 150;
            int step = 10;
            if (intensityThs< max)
            {
                intensityThs += step;
                return true;
            }
            else
            {
                return false;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Application.Idle -= ProcessFrame;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Application.Idle += ProcessFrame;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            ProcessFrame(this, null);
        }

        private void DrawDot(Image<Bgr, Byte> tmp, Point p, bool isModel)
        {        
            CircleF cir = new CircleF(ToPointF(p), 10);
            tmp.Draw(cir, new Bgr(isModel? Color.Blue:Color.Red), 2);
        }
        
        private void DrawDot(Image<Gray, float> tmp, Point p)
        {
            CircleF cir = new CircleF(ToPointF(p), 10);
            tmp.Draw(cir, new Gray(255), 2);
        }

        public static PointF ToPointF(System.Drawing.Point p)
        {
            return new PointF(p.X, p.Y);
        }

        public static double CountDistance(PointF p, PointF p2)
        {
            double l = Math.Sqrt(Math.Pow(Math.Abs(p.X - p2.X), 2.0) + Math.Pow(Math.Abs(p.Y - p2.Y), 2.0));
            return l;
        }

        public void OpenVideo(String file)
        {
            pr = ObjectXMLSerializer<PointRegister>.Load(file + ".xml");
            capture = new Capture(file);
            length = (int)capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
            position = 0;
            filename = new FileInfo(file).Name;
            lastpos = -1;
            samecount = 0;
            output = new System.Text.StringBuilder();
        }
    }
}
